import hashlib
import os
from pathlib import Path
from tokenize import String
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
from flask import Blueprint, jsonify, Flask, current_app, make_response, request
from flask_jwt_extended import jwt_required, get_jwt_identity
from exts import db
from mimetypes import MimeTypes
from flask import Blueprint,current_app, jsonify, send_from_directory
from flask_restx import Resource, Api,reqparse
import config
from utils.http import success_api, fail_api
from models.attachment import Attachment
from utils.random import rand_str, rand_file

file_bp = Blueprint("file",__name__,url_prefix="/file")
api = Api(file_bp)

BASE_DIR = os.path.dirname(os.path.realpath(__file__))
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'media')
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif','webp'}


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@api.route('/upload')
class Upload(Resource):
    @staticmethod
    def allowed_file(filename):
        return '.' in filename and \
               filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
    @staticmethod
    def get_file_md5(file):
        with open(file, "rb") as f:
            f.seek(0)
            md5 = hashlib.md5()
            for line in f.readlines():
                md5.update(line)
            m = md5.hexdigest()
        return m
    @staticmethod
    def get_file_sha1(file):
        with open(file, "rb") as f:
            f.seek(0)
            sha1 = hashlib.sha1()
            for line in f.readlines():
                sha1.update(line)
            m = sha1.hexdigest()
        return m

    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('file', required=True, type=FileStorage, location='files')
        parser.add_argument('title', type=FileStorage, location='files')
        args = parser.parse_args()
        file = args['file']  # 获取文件对象
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)  # 校验文件名称合法
            extension = file.filename.split('.')[1]
            name = "".join(rand_file())+"."+extension
            file.save(os.path.join(current_app.config.get('UPLOAD_FOLDER'), name))
            url = f'/images/{name}'
            file_mime = MimeTypes()
            path = f'./upload/{name}'
            mime_type = file_mime.guess_type(path)
            size = os.path.getsize(f"./upload/{name}")
            sha1 = self.get_file_sha1(path)
            md5 = self.get_file_md5(path)
            att = Attachment.query.filter_by(sha1=sha1, md5=md5).first()
            #文件存在删除新增文件
            if att:
                os.remove(os.path.join("./upload", name))  # 删除文件
                return success_api("上传成功",att)
            attachment = Attachment(
                name= name,
                path = path,
                code=rand_str(),
                size=size,
                mime=mime_type[0],
                sha1=sha1,
                extension=extension,
                md5 = md5,
                driver="public",
                status=1,
                url =url,
            )
            db.session.add(attachment)
            db.session.commit()

            return success_api("上传成功",attachment)
        else:
            return fail_api("文件格式不支持")


@file_bp.get('/list')
@jwt_required(optional=False)
def fileList():
    per_page = int(request.args.get("per_page") or 10)
    page = int(request.args.get("page") or 1)
    #user_name = request.args.get("user_name")
    query = Attachment.query.order_by(Attachment.id.desc())
    count = query.count()
    data = query.limit(per_page).offset((page - 1) * per_page).all()
    list = {"count": count, "list": data, "per_page": per_page, "page": page}
    return success_api("成功", list)

@file_bp.delete('/<int:id>')
@jwt_required(optional=False)
def deleteList(id):
    file = Attachment.query.get(id)
    try:
        db.session.delete(file)
        db.session.commit()
        os.remove(os.path.join("./upload", file.name))  # 删除文件
        return success_api("删除成功")
    except:
        return fail_api("删除失败")

